package com.meilai.project.service.business.building.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.constant.BuildingCorrespondingPointEnum;
import com.meilai.project.controller.mini.dto.MiniSearchBuildingParams;
import com.meilai.project.controller.mini.vo.MiniBuildingVO;
import com.meilai.project.controller.web.report.service.WeekReportService;
import com.meilai.project.controller.web.report.vo.WeekDetailCustomerExt2;
import com.meilai.project.controller.web.report.vo.WeekDetailVO2;
import com.meilai.project.controller.web.report.vo.WeekDetailVO3;
import com.meilai.project.dto.business.building.*;
import com.meilai.project.dto.thirdPart.LocationPoint;
import com.meilai.project.entity.business.building.BuildingArea;
import com.meilai.project.entity.business.building.BuildingAreaForbidIndustry;
import com.meilai.project.entity.business.building.BuildingAreaPoint;
import com.meilai.project.entity.media.MediaPoint;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.business.building.BuildingAreaAudienceRelationMapper;
import com.meilai.project.mapper.business.building.BuildingAreaMapper;
import com.meilai.project.mapper.business.building.BuildingAreaPointMapper;
import com.meilai.project.mapper.business.media.MediaTypeMapper;
import com.meilai.project.service.business.building.BuildingAreaForbidIndustryService;
import com.meilai.project.service.business.building.BuildingAreaPointService;
import com.meilai.project.service.business.building.BuildingAreaService;
import com.meilai.project.service.business.media.MediaPointService;
import com.meilai.project.service.media.MediaPointOccupySnapshotService;
import com.meilai.project.util.FileUtil;
import com.meilai.project.vo.IdNameVO;
import com.meilai.project.vo.business.building.*;
import com.meilai.project.vo.business.media.MediaTypeExtVO;
import com.meilai.project.vo.business.media.MediaTypeForBuildingTypeVO;
import com.meilai.project.vo.business.media.MediaTypeVO;
import com.meilai.project.vo.other.SearchAreaVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 张驰
 * @date 2022/1/9 23:02
 */
@Service
@Slf4j
public class BuildingAreaServiceImpl extends ServiceImpl<BuildingAreaMapper, BuildingArea> implements BuildingAreaService {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");

    @Autowired
    private MediaTypeMapper mediaTypeMapper;

    @Autowired
    private BuildingAreaAudienceRelationMapper buildingAreaAudienceRelationMapper;

    @Autowired
    private BuildingAreaForbidIndustryService buildingAreaForbidIndustryService;

    @Autowired
    private BuildingAreaPointService buildingAreaPointService;

    @Autowired
    private BuildingAreaPointMapper buildingAreaPointMapper;

    @Autowired
    private MediaPointService mediaPointService;

    @Autowired
    private MediaPointOccupySnapshotService mediaPointOccupySnapshotService;

    @Autowired
    private WeekReportService weekReportService;

    @Value("${static-resource.file-space}")
    private String tmpPath;

    @Override
    public List<MiniBuildingVO> listByConditionForMini(MiniSearchBuildingParams searchDTO) {
        return baseMapper.listByConditionForMini(searchDTO);
    }

    @Override
    public MapPointDTO getMapCenter(HttpServletRequest request) {
        MapPointDTO dto = null;
//        List<BuildingArea> list = list(new QueryWrapper<BuildingArea>().isNull("deleted_at").eq("status", 1).isNotNull("lat").isNotNull("lng"));
//        if (CollectionUtils.isNotEmpty(list)) {
//            // 有楼盘时
//            BigDecimal min_lat = new BigDecimal("53");
//            BigDecimal max_lat = new BigDecimal("0");
//            BigDecimal min_lng = new BigDecimal("135");
//            BigDecimal max_lng = new BigDecimal("0");
//
//            for (BuildingArea item : list) {
//                if (min_lat.compareTo(item.getLat()) > 0) min_lat = item.getLat();
//                if (max_lat.compareTo(item.getLat()) < 0) max_lat = item.getLat();
//                if (min_lng.compareTo(item.getLng()) > 0) min_lng = item.getLng();
//                if (max_lng.compareTo(item.getLng()) < 0) max_lng = item.getLng();
//            }
//
//
//        }
        BigDecimal min_lat = new BigDecimal("31.768731");
        BigDecimal max_lat = new BigDecimal("31.782578");
        BigDecimal min_lng = new BigDecimal("119.944038");
        BigDecimal max_lng = new BigDecimal("119.978159");
        dto = new MapPointDTO(min_lat.add(max_lat).divide(new BigDecimal("2"), 10, BigDecimal.ROUND_HALF_UP),
                min_lng.add(max_lng).divide(new BigDecimal("2"), 10, BigDecimal.ROUND_HALF_UP));
        dto.setAdcode(320400L);
        dto.setNe(new LocationPoint(max_lat, min_lng));
        dto.setSw(new LocationPoint(min_lat, max_lng));
        return dto;
    }

    @Override
    public BuildingAreaDetailVO getDetail(Long id) {
        BuildingAreaDetailVO vo = new BuildingAreaDetailVO();
        BuildingArea ba = getById(id);
        if (ba == null) return vo;
        BeanUtils.copyProperties(ba, vo);
        List<BuildingAreaDetailPointVO> points = buildingAreaPointMapper.getDetailPoints(id);
        if (CollectionUtils.isNotEmpty(points)) vo.setPoints(points);
        return vo;
    }

    @Override
    public List<BuildingAreaWebBaseVO> listAll(String ad_code) {
        return baseMapper.listAll(ad_code);
    }

    @Override
    public List<IdNameVO> listAllSimple(String ad_code) {
        return baseMapper.listAllSimple(ad_code);
    }

    @Override
    public Page<BuildingAreaWebVO> selectPageList(Integer current_page, Integer page_size, BuildingAreaDTO buildingArea) {
        Page<BuildingAreaWebVO> page = new Page<BuildingAreaWebVO>(current_page, page_size);
        List<BuildingAreaWebVO> list = baseMapper.selectPageList(page, buildingArea);
        return page.setRecords(handleList(list));
    }

    @Override
    public List<BuildingAreaWebMapVO> getListForMap(LocationPoint sw, LocationPoint ne, DateRangeDTO dateRange) {
        List<BuildingAreaWebMapVO> results = baseMapper.selectIdNameBySWNE(sw.getLat(), ne.getLat(), sw.getLng(), ne.getLng());
        if (CollectionUtils.isNotEmpty(results)) {
            Map<Long, Map<Long, BuildingAreaPointSumNumsVO>> pointNumSum = getPointNumSum(dateRange);
            for (BuildingAreaWebMapVO b : results) {
                Map<Long, BuildingAreaPointSumNumsVO> nums = pointNumSum.getOrDefault(b.getId(), new HashMap<>());
                Integer point_sum = 0;
                if (nums.size() > 0)
                    for (BuildingAreaPointSumNumsVO num : nums.values()) {
                        point_sum += num.getNum();
                    }
                b.setPoint_num_sum(nums);
                b.setPoint_sum(point_sum);
            }
        }
        return results;
    }

    private Map<Long, Map<Long, BuildingAreaPointSumNumsVO>> getPointNumSum(DateRangeDTO dateRange) {
        Map<Long, Map<Long, BuildingAreaPointSumNumsVO>> results = new HashMap<>();
        List<BuildingAvaAllMPCountVO> baseNums = baseMapper.selectBuildingAvaAllMPCount(dateRange.getStart_at(), dateRange.getEnd_at());
        List<BuildingOccupyMPCountVO> occupyNums = baseMapper.selectBuildingOccupyMPCount(dateRange.getStart_at(), dateRange.getEnd_at());

        HashMap<Long, HashMap<Long, Integer>> availableMap = new HashMap<>();
        HashMap<Long, HashMap<Long, Integer>> allMap = new HashMap<>();
        HashMap<Long, HashMap<Long, Integer>> lockedMap = new HashMap<>();
        HashMap<Long, HashMap<Long, Integer>> usedMap = new HashMap<>();
        HashSet<Long> buildingIdsSet = new HashSet<>();
        if (CollectionUtils.isNotEmpty(baseNums)) {
            for (BuildingAvaAllMPCountVO baseNum : baseNums) {
                Long building_area_id = baseNum.getBuilding_area_id();
                Long media_type_id = baseNum.getMedia_type_id();

                HashMap<Long, Integer> availableP = availableMap.getOrDefault(building_area_id, new HashMap<>());
                availableP.put(baseNum.getMedia_type_id(), baseNum.getAvailable_num() + availableP.getOrDefault(media_type_id, 0));
                availableMap.put(building_area_id, availableP);

                HashMap<Long, Integer> allP = allMap.getOrDefault(building_area_id, new HashMap<>());
                allP.put(baseNum.getMedia_type_id(), baseNum.getNum() + allP.getOrDefault(media_type_id, 0));
                allMap.put(building_area_id, allP);

                buildingIdsSet.add(baseNum.getBuilding_area_id());
            }
        }
        if (CollectionUtils.isNotEmpty(occupyNums)) {
            for (BuildingOccupyMPCountVO occupyNum : occupyNums) {
                Long building_area_id = occupyNum.getBuilding_area_id();
                Long media_type_id = occupyNum.getMedia_type_id();

//                if (occupyNum.getOccupy_type().equals(1) || occupyNum.getOccupy_type().equals(4)) {
//                    HashMap<Long, Integer> lockedP = lockedMap.getOrDefault(building_area_id, new HashMap<>());
//                    lockedP.put(occupyNum.getMedia_type_id(), occupyNum.getNum() + lockedP.getOrDefault(media_type_id, 0));
//                    lockedMap.put(building_area_id, lockedP);
//                }
//                if (occupyNum.getOccupy_type().equals(2) || occupyNum.getOccupy_type().equals(3)) {
//                    HashMap<Long, Integer> usedP = usedMap.getOrDefault(building_area_id, new HashMap<>());
//                    usedP.put(occupyNum.getMedia_type_id(), occupyNum.getNum() + usedP.getOrDefault(media_type_id, 0));
//                    usedMap.put(building_area_id, usedP);
//                }

                // 改版后，仅有2个值，1：方案，4：手动锁定
                if (occupyNum.getOccupy_type().equals(4)) {
                    HashMap<Long, Integer> lockedP = lockedMap.getOrDefault(building_area_id, new HashMap<>());
                    lockedP.put(occupyNum.getMedia_type_id(), occupyNum.getNum() + lockedP.getOrDefault(media_type_id, 0));
                    lockedMap.put(building_area_id, lockedP);
                }
                if (occupyNum.getOccupy_type().equals(1)) {
                    HashMap<Long, Integer> usedP = usedMap.getOrDefault(building_area_id, new HashMap<>());
                    usedP.put(occupyNum.getMedia_type_id(), occupyNum.getNum() + usedP.getOrDefault(media_type_id, 0));
                    usedMap.put(building_area_id, usedP);
                }

                buildingIdsSet.add(occupyNum.getBuilding_area_id());
            }
        }
        if (CollectionUtils.isNotEmpty(buildingIdsSet)) {
            for (Long bId : buildingIdsSet) {
                Map<Long, BuildingAreaPointSumNumsVO> mpt_Map = results.getOrDefault(bId, new HashMap<>());
                HashMap<Long, Integer> mpt_allMap = allMap.getOrDefault(bId, new HashMap<>());
                HashMap<Long, Integer> mpt_availableMap = availableMap.getOrDefault(bId, new HashMap<>());
                HashMap<Long, Integer> mpt_lockedMap = lockedMap.getOrDefault(bId, new HashMap<>());
                HashMap<Long, Integer> mpt_usedMap = usedMap.getOrDefault(bId, new HashMap<>());
                if (mpt_allMap.size() > 0) {
                    for (Map.Entry<Long, Integer> allEntry : mpt_allMap.entrySet()) {
                        BuildingAreaPointSumNumsVO temp = new BuildingAreaPointSumNumsVO();
                        temp.setDevice_num(allEntry.getValue());
                        temp.setNum(allEntry.getValue());
                        temp.setAvailable_num(mpt_availableMap.getOrDefault(allEntry.getKey(), 0));
                        temp.setLocked_num(mpt_lockedMap.getOrDefault(allEntry.getKey(), 0));
                        temp.setUsed_num(mpt_usedMap.getOrDefault(allEntry.getKey(), 0));
                        temp.setInstalled_num(allEntry.getValue());
                        mpt_Map.put(allEntry.getKey(), temp);
                    }
                }
                results.put(bId, mpt_Map);
            }
        }
        return results;
    }

    private List<BuildingAreaWebVO> handleList(List<BuildingAreaWebVO> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> ids = list.stream().map(BuildingAreaWebVO::getId).collect(Collectors.toList());
            List<MediaPoint> baps = mediaPointService.list(Wrappers.<MediaPoint>lambdaQuery().isNull(MediaPoint::getDeleted_at).in(MediaPoint::getBuilding_area_id, ids));

            List<BuildingAreaPoint> baPoints = buildingAreaPointService.list(Wrappers.lambdaQuery(BuildingAreaPoint.class).in(BuildingAreaPoint::getBuilding_area_id, ids));
            Map<Long, List<BuildingAreaPoint>> baPointsMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(baPoints))
                baPointsMap = baPoints.stream().collect(Collectors.groupingBy(BuildingAreaPoint::getBuilding_area_id));
            HashMap<Long, HashMap<Long, Long>> uninstallMediaMap = new HashMap<>();

            // 媒体类型Map key是楼盘ID value是媒体类型为key的map（里面的value是媒体类型规格为key数量为值的map）
            HashMap<Long, HashMap<Long, HashMap<Long, Long>>> mediaMap = new HashMap<>();
            HashMap<Long, HashMap<Long, HashMap<Long, Long>>> lockMediaMap = new HashMap<>();
            Map<Long, List<MediaPoint>> buildingPointMap = baps.stream().collect(Collectors.groupingBy(MediaPoint::getBuilding_area_id));
            if (CollectionUtils.isNotEmpty(baps)) {

                Map<Long, List<BuildingAreaPoint>> finalBaPointsMap = baPointsMap;

                // 找出所有被占用的点位
                List<Long> lockPointIds = mediaPointOccupySnapshotService.getLockPointIdsByIds(baps.stream().map(MediaPoint::getId).collect(Collectors.toList()));
                buildingPointMap.forEach((key, value) -> {
                    // 点位类型Map
                    Map<Long, List<MediaPoint>> mediaTypeMap = value.stream().collect(Collectors.groupingBy(MediaPoint::getMedia_type_id));
                    HashMap<Long, HashMap<Long, Long>> innerMap = new HashMap<>();
                    HashMap<Long, HashMap<Long, Long>> lockMap = new HashMap<>();
                    mediaTypeMap.forEach((mediaTypeId, mediaTypeList) -> {
                        // 具有规格的点位Map
                        Map<Long, List<MediaPoint>> hasMediaTypeSpecIdPointMap = mediaTypeList.stream().filter(point -> point.getMedia_type_spec_id() != null).collect(Collectors.groupingBy(MediaPoint::getMedia_type_spec_id));
                        // 没有规格的点位List
                        List<MediaPoint> notHasMediaTypeSpecIdPointList = mediaTypeList.stream().filter(point -> point.getMedia_type_spec_id() == null).collect(Collectors.toList());
                        HashMap<Long, Long> mediaTypeSpecMap = new HashMap<>();
                        HashMap<Long, Long> lockMediaTypeSpecMap = new HashMap<>();
                        if (notHasMediaTypeSpecIdPointList.size() > 0) {
                            List<MediaPoint> lockPointList = notHasMediaTypeSpecIdPointList.stream().filter(item -> !lockPointIds.contains(item.getId())).collect(Collectors.toList());
                            mediaTypeSpecMap.put(-1L, Long.parseLong(notHasMediaTypeSpecIdPointList.size() + ""));
                            lockMediaTypeSpecMap.put(-1L, Long.parseLong(lockPointList.size() + ""));
                        }
                        hasMediaTypeSpecIdPointMap.forEach((mediaTypeSpecId, mediaTypeSpecList) -> {
                            List<MediaPoint> lockPointList = mediaTypeSpecList.stream().filter(item -> !lockPointIds.contains(item.getId())).collect(Collectors.toList());
                            mediaTypeSpecMap.put(mediaTypeSpecId, Long.parseLong(mediaTypeSpecList.size() + ""));
                            lockMediaTypeSpecMap.put(mediaTypeSpecId, Long.parseLong(lockPointList.size() + ""));
                        });
                        innerMap.put(mediaTypeId, mediaTypeSpecMap);
                        lockMap.put(mediaTypeId, lockMediaTypeSpecMap);
                    });
                    mediaMap.put(key, innerMap);
                    lockMediaMap.put(key, lockMap);

                    List<BuildingAreaPoint> BAPoints = finalBaPointsMap.getOrDefault(key, new ArrayList<>());
                    HashMap<Long, HashMap<Long, Long>> mtCountMap = mediaMap.getOrDefault(key, new HashMap<>());
                    if (CollectionUtils.isNotEmpty(BAPoints)) {
                        HashMap<Long, Long> uninstallCount = new HashMap<>();
                        Map<Long, Long> pCount = BAPoints.stream().collect(Collectors.toMap(BuildingAreaPoint::getMedia_type_id, BuildingAreaPoint::getNum, (k1, k2) -> k2));
                        if (pCount.size() > 0) {
                            for (Map.Entry<Long, Long> entry : pCount.entrySet()) {
                                Long mtId = entry.getKey();
                                Long defaultCount = entry.getValue();
                                HashMap<Long, Long> specsCountMap = mtCountMap.getOrDefault(mtId, new HashMap<>());
                                Long installSumCount = 0L;
                                if (specsCountMap != null && specsCountMap.size() > 0) {
                                    for (Long count : specsCountMap.values()) {
                                        installSumCount += count;
                                    }
                                }
                                if (defaultCount > installSumCount) {
                                    uninstallCount.put(mtId, defaultCount - installSumCount);
                                }
                            }
                        }
                        if (uninstallCount.size() > 0) uninstallMediaMap.put(key, uninstallCount);
                    }

                });
//                baps.forEach(d -> {
//                    innerMap.put(d.getMedia_type_id(), d.getNum());
//                    mediaMap.put(d.getBuilding_area_id(), innerMap);
//                });
            }
            list.forEach(d -> {
                if (StringUtils.isNotEmpty(d.getAudience_ids_str())) {
                    String[] audience_ids_s = d.getAudience_ids_str().split(",");
                    for (String s : audience_ids_s) {
                        d.getAudience_ids().add(Long.valueOf(s));
                    }
                }
                if (StringUtils.isNotEmpty(d.getForbid_industry_ids_str())) {
                    String[] forbid_industry_ids_s = d.getForbid_industry_ids_str().split(",");
                    for (String s : forbid_industry_ids_s) {
                        d.getForbid_industry_ids().add(Long.valueOf(s));
                    }
                }
                d.setMedia_types(mediaMap.getOrDefault(d.getId(), new HashMap<>()));
                d.setFree_media_types(lockMediaMap.getOrDefault(d.getId(), new HashMap<>()));
                d.setUninstall_media_types(uninstallMediaMap.getOrDefault(d.getId(), new HashMap<>()));
                d.setPoint_total_count(buildingPointMap.getOrDefault(d.getId(), new ArrayList<>()).size());
            });
        }
        return list;
    }

    @Override
    @Transactional
    public boolean alinePointNum() {
        List<BuildingAreaPoint> baps = buildingAreaPointMapper.getBuildingPoints(null);
        buildingAreaPointService.remove(new QueryWrapper<>());
        buildingAreaPointService.saveBatch(baps);
        return true;
    }

    @Override
    @Transactional
    public boolean alinePointNum(Long id) {
        List<BuildingAreaPoint> baps = buildingAreaPointMapper.getBuildingPoints(id);
        buildingAreaPointService.remove(new QueryWrapper<BuildingAreaPoint>().eq("building_area_id", id));
        buildingAreaPointService.saveBatch(baps);
        return true;
    }

    @Override
    @Transactional
    public boolean addOne(BuildingAreaDTO params) {
        BuildingArea temp = new BuildingArea();
        BeanUtils.copyProperties(params, temp);

        HashMap<String, BigDecimal> location = checkLatLng(temp.getLat(), temp.getLng());
        temp.setLat(location.get("lat"));
        temp.setLng(location.get("lng"));
        return save(temp)
                && updateBuildingAreaPoints(temp.getId(), params.getPoints())
                && updateBuildingAreaAudienceRelation(temp.getId(), params.getAudience_ids())
                && updateBuildingAreaForbidIndustry(temp.getId(), params.getForbid_industry_ids());
    }

    @Override
    @Transactional
    public boolean editOne(BuildingAreaDTO params) {
        if (params.getId() == null) throw new CommonException("当前楼盘不存在");
        BuildingArea temp = new BuildingArea();
        BeanUtils.copyProperties(params, temp);

        return updateById(temp)
                && updateBuildingAreaPoints(temp.getId(), params.getPoints())
                && updateBuildingAreaAudienceRelation(temp.getId(), params.getAudience_ids())
                && updateBuildingAreaForbidIndustry(temp.getId(), params.getForbid_industry_ids());
    }

    @Override
    @Transactional
    public boolean delOne(Long id) {
        BuildingArea temp = new BuildingArea();
        temp.setId(id);
        temp.setDeleted_at(LocalDateTime.now());
        return updateById(temp)
                && mediaPointService.update(Wrappers.lambdaUpdate(MediaPoint.class)
                .set(MediaPoint::getDeleted_at, LocalDateTime.now())
                .eq(MediaPoint::getBuilding_area_id, id));
    }

    /**
     * 检查当前经度是否已存在点位，存在则进行偏移
     */
    private HashMap<String, BigDecimal> checkLatLng(BigDecimal lat, BigDecimal lng) {
        List<BuildingArea> list = baseMapper.selectList(new QueryWrapper<BuildingArea>().isNull("deleted_at").eq("lat", lat).eq("lng", lng));
        if (CollectionUtils.isNotEmpty(list)) {
            return checkLatLng(lat.subtract(new BigDecimal("0.0005")), lng.subtract(new BigDecimal("0.0005")));
        } else {
            HashMap<String, BigDecimal> map = new HashMap<>();
            map.put("lat", lat);
            map.put("lng", lng);
            return map;
        }
    }

    @Override
    public List<SearchAreaVO> selectSearchAreaVO() {
        return baseMapper.selectSearchAreaVO();
    }

    @Override
    public List<MediaTypeVO> getMediaTypes() {
        return mediaTypeMapper.getMediaTypes();
    }

    @Override
    public List<MediaTypeForBuildingTypeVO> getMediaTypesForBuildingType() {
        return mediaTypeMapper.getMediaTypesWithBuildingType();
    }

    @Override
    public List<MediaTypeVO> getMediaTypesNotIncludeGasStation() {
        return mediaTypeMapper.getMediaTypesNotIncludeGasStation();
    }

    @Override
    public List<MediaTypeExtVO> listMediaTypes() {
        return mediaTypeMapper.listMediaTypes();
    }

    @Override
    public List<MediaTypeVO> getMediaTypesOfGasStation() {
        return mediaTypeMapper.getMediaTypesOfGasStation();
    }

    /**
     * 根据项目id，更新子表（项目点位数量）
     */
    private boolean updateBuildingAreaPoints(Long buildingAreaId, List<BuildingAreaPoint> points) {
        buildingAreaPointService.remove(new QueryWrapper<BuildingAreaPoint>().eq("building_area_id", buildingAreaId));
        if (CollectionUtils.isNotEmpty(points)) {
            List<BuildingAreaPoint> list = points.stream().peek(item -> item.setBuilding_area_id(buildingAreaId)).collect(Collectors.toList());
            return buildingAreaPointService.saveBatch(list);
        }
        return true;
    }

    /**
     * 根据项目id，删除项目和受众描述对应关系数据，重新插入新的关系数据
     */
    private boolean updateBuildingAreaAudienceRelation(Long buildingAreaId, List<Long> audienceIds) {
        buildingAreaAudienceRelationMapper.deleteByBuildingAreaId(buildingAreaId);
        if (CollectionUtils.isNotEmpty(audienceIds)) {
            return buildingAreaAudienceRelationMapper.insertRelations(buildingAreaId, audienceIds);
        }
        return true;
    }

    /**
     * 根据项目id，更新子表（项目禁止行业）
     */
    private boolean updateBuildingAreaForbidIndustry(Long buildingAreaId, List<Long> forbidIndustryIds) {
        buildingAreaForbidIndustryService.remove(new QueryWrapper<BuildingAreaForbidIndustry>().eq("building_area_id", buildingAreaId));
        if (CollectionUtils.isNotEmpty(forbidIndustryIds)) {
            List<BuildingAreaForbidIndustry> bafis = forbidIndustryIds.stream().map(id -> {
                BuildingAreaForbidIndustry bafi = new BuildingAreaForbidIndustry();
                bafi.setBuilding_area_id(buildingAreaId);
                bafi.setForbid_industry_id(id);
                return bafi;
            }).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(bafis)) {
                return buildingAreaForbidIndustryService.saveBatch(bafis);
            }
        }
        return true;
    }

    @Override
    public BuildingAreaWebVO one(Long id) {
        BuildingAreaWebVO vo = baseMapper.one(id);
        if (vo == null) {
            throw new CommonException("id不存在");
        }
        List<BuildingAreaWebVO> list = new ArrayList<>();
        list.add(vo);
        List<BuildingAreaWebVO> vos = handleList(list);
        return vos.get(0);
    }

    @Override
    public void getBuildingImportExcel(HttpServletResponse response) {
        List<BuildingArea> list = baseMapper.selectList(Wrappers.<BuildingArea>lambdaQuery().isNull(BuildingArea::getDeleted_at));
        List<BuildingExcelVO> data = list.stream().map(item -> {
            BuildingExcelVO vo = new BuildingExcelVO();
            vo.setName(item.getName());
            return vo;
        }).collect(Collectors.toList());
        try {
            EasyExcel.write(response.getOutputStream(), BuildingExcelVO.class)
                    .sheet("选位导入楼盘模板")
                    .doWrite(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<Long> getSelectBuildingIds(MultipartFile file) {
        List<BuildingExcelVO> list = new ArrayList<>();
        try {
            EasyExcel.read(file.getInputStream(), BuildingExcelVO.class, new AnalysisEventListener<BuildingExcelVO>() {
                @Override
                public void invoke(BuildingExcelVO buildingExcelVO, AnalysisContext analysisContext) {
                    list.add(buildingExcelVO);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {

                }
            }).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (CollectionUtils.isNotEmpty(list)) {
            List<String> collect = list.stream().filter(item -> StringUtils.isNotBlank(item.getName())).map(BuildingExcelVO::getName).collect(Collectors.toList());
            List<BuildingArea> data = new ArrayList<>();
            if(CollectionUtil.isNotEmpty(collect))
                data = baseMapper.selectList(Wrappers.<BuildingArea>lambdaQuery().in(BuildingArea::getName, collect));
            return data.stream().map(BuildingArea::getId).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    @Override
    public void exportBuildingMediaPointExcel(HttpServletResponse response, List<Long> building_ids) {
        List<BuildingArea> buildingList = baseMapper.selectList(Wrappers.<BuildingArea>lambdaQuery().select(BuildingArea::getId, BuildingArea::getName).eq(BuildingArea::getType_id, BuildingCorrespondingPointEnum.RESIDENCE.getBuilding_type_id()).in(BuildingArea::getId, building_ids));
        if (CollectionUtils.isEmpty(buildingList)) throw new CommonException("暂无可导出数据");
        List<Long> ids = buildingList.stream().map(BuildingArea::getId).collect(Collectors.toList());
        Map<Long, String> buildingMap = buildingList.stream().collect(Collectors.toMap(BuildingArea::getId, BuildingArea::getName));
        List<WeekDetailVO3> list = weekReportService.weekDetail2(ids);
        // 客户
//        Map<Long, Long> inPublishCustomerMap = new HashMap<>();
//        Map<Long, Long> waitPublishCustomerMap = new HashMap<>();
//        for (WeekDetailVO2 vo2 : list) {
//            List<WeekDetailCustomerExt2> inPublish = vo2.getInPublish();
//            List<WeekDetailCustomerExt2> waitPublish = vo2.getWaitPublish();
//            for (WeekDetailCustomerExt2 ext2 : inPublish) {
//                Long customerId = ext2.getCustomerId();
//                inPublishCustomerMap.put(customerId, customerId);
//            }
//            for (WeekDetailCustomerExt2 ext2 : waitPublish) {
//                Long customerId = ext2.getCustomerId();
//                waitPublishCustomerMap.put(customerId, customerId);
//            }
//        }
        // 获取拍照要求

        // 获取每个楼盘的数据
        //Map<String, List<WeekDetailVO2>> dataMap = list.stream().collect(Collectors.toMap(WeekDetailVO3::getBuilding_id, WeekDetailVO3::getWeekDetailVO2List, (k1, k2) -> k2));
        String now = LocalDate.now().format(formatter);
        List<File> fileList = new ArrayList<>();
        for (WeekDetailVO3 one : list) {
            String building_name = buildingMap.get(Long.valueOf(one.getBuilding_id()));
            String fileName = tmpPath + File.separator + building_name + now + System.currentTimeMillis() + ".xls";
            HSSFWorkbook excel = createExcelByBuildingMediaPoint(building_name, one);
            File file = new File(fileName);
            fileList.add(file);
            FileOutputStream out = null;
            try {
                if (!file.exists()) {
                    file.createNewFile();
                }
                out = new FileOutputStream(file);
                excel.write(out);
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    try {
                        out.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        String zipFilePath = null;
        FileInputStream input = null;
        try {
            zipFilePath = FileUtil.zipFile(fileList, tmpPath + File.separator + "导出上刊点位" + System.currentTimeMillis());
            File zip = new File(zipFilePath);
            input = new FileInputStream(zip);
            ServletOutputStream out = response.getOutputStream();
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("test.zip", "UTF-8"));
            byte[] bytes = new byte[1024];
            while (input.read(bytes) != -1) {
                out.write(bytes);
            }
            out.flush();
            input.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (zipFilePath != null) {
                FileUtil.delFile(zipFilePath);// 删除文件
                for (File file : fileList) {
                    file.delete();
                }
            }
        }
    }

    @Override
    public void exportBuildingMediaPointExcelToOneExcel(HttpServletResponse response, List<Long> building_ids) {
        List<BuildingArea> buildingList = baseMapper.selectList(Wrappers.<BuildingArea>lambdaQuery().select(BuildingArea::getId, BuildingArea::getName)
                .eq(BuildingArea::getType_id, BuildingCorrespondingPointEnum.RESIDENCE.getBuilding_type_id())
                .in(BuildingArea::getId, building_ids));

        if (CollectionUtils.isEmpty(buildingList)) throw new CommonException("暂无可导出数据");
        List<Long> ids = buildingList.stream().map(BuildingArea::getId).collect(Collectors.toList());
        Map<Long, String> buildingMap = buildingList.stream().collect(Collectors.toMap(BuildingArea::getId, BuildingArea::getName));
        List<WeekDetailVO3> list = weekReportService.weekDetail2(ids);

        // 创建表格对象
        HSSFWorkbook wb = new HSSFWorkbook();

        HSSFCellStyle tbodyCellStyle = setExcelTbodyCellStyle(wb);
        HSSFCellStyle theadCellStyle = setExcelTheadCellStyle(wb, tbodyCellStyle);
        HSSFCellStyle titleCellStyle = setExcelTitleCellStyle(wb, tbodyCellStyle);
        HSSFCellStyle leftCellStyle = setExcelLeftCellStyle(wb, tbodyCellStyle);
        HSSFCellStyle font12CellStyle = setExcelFont12CellStyle(wb, tbodyCellStyle);

        for (int i = 0; i < list.size(); i++) {
            WeekDetailVO3 one = list.get(i);
            int index = (i+1);
            String building_name = buildingMap.get(Long.valueOf(one.getBuilding_id()));
            HSSFSheet sheet = wb.createSheet(index + building_name + "（" + one.getPointCount() + "幅）");
            createExcelByBuildingMediaPoint2(sheet,
                    tbodyCellStyle, theadCellStyle, titleCellStyle, leftCellStyle, font12CellStyle,
                    building_name, one);
        }

        try {
            response.setContentType("application/msexcel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("test.xls", "UTF-8"));
            OutputStream out = response.getOutputStream();
            wb.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static HSSFWorkbook createExcelByBuildingMediaPoint(String building_name, WeekDetailVO3 oneBuilding) {
        List<WeekDetailVO2> list = oneBuilding.getWeekDetailVO2List();
        // 创建表格对象
        HSSFWorkbook wb = new HSSFWorkbook();
        /**
         * 单元格样式
         */
        HSSFCellStyle tbodyCellStyle = setExcelTbodyCellStyle(wb);
        HSSFCellStyle theadCellStyle = setExcelTheadCellStyle(wb, tbodyCellStyle);
        HSSFCellStyle titleCellStyle = setExcelTitleCellStyle(wb, tbodyCellStyle);
        HSSFCellStyle leftCellStyle = setExcelLeftCellStyle(wb, tbodyCellStyle);
        HSSFCellStyle font12CellStyle = setExcelFont12CellStyle(wb, tbodyCellStyle);

        // 基础列
        String[] theadArr = new String[]{"序号", "栋数", "单元", "楼层", "数量", "类型", "在刊客户", "待上刊客户"};
        int theadLength = theadArr.length, index = theadLength - 1;

        // 创建sheet
        HSSFSheet sheet = wb.createSheet();
        // 创建拍照要求
        setExcelByShootRequirement(sheet, font12CellStyle, leftCellStyle, index,
                String.join("", oneBuilding.getToInPublishShootRequirements()),
                String.join("", oneBuilding.getToUnPublishShootRequirements()));
        // 创建表头
        HSSFRow row3 = sheet.createRow(2);
        row3.setHeight((short) (25 * 20));
        HSSFCell cell3 = row3.createCell(0);
        cell3.setCellValue(building_name + "（" + oneBuilding.getPointCount() + "幅）");
        cell3.setCellStyle(titleCellStyle);
        // 设置跨行
        CellRangeAddress cellAddresses = new CellRangeAddress(2, 2, 0, index);
        sheet.addMergedRegion(cellAddresses);
        RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses, sheet);
        // 设置表头
        HSSFRow row4 = sheet.createRow(3);
        row4.setHeight((short) (30 * 20));
        setExcelThead(sheet, row4, theadCellStyle, theadArr);

        // 设置表格内容
        fillExcelTbody(sheet, tbodyCellStyle, 4, theadLength, list);

        return wb;
    }

    public static void createExcelByBuildingMediaPoint2(HSSFSheet sheet,
                                                        HSSFCellStyle tbodyCellStyle,
                                                        HSSFCellStyle theadCellStyle,
                                                        HSSFCellStyle titleCellStyle,
                                                        HSSFCellStyle leftCellStyle,
                                                        HSSFCellStyle font12CellStyle,
                                                        String building_name, WeekDetailVO3 oneBuilding) {
        List<WeekDetailVO2> list = oneBuilding.getWeekDetailVO2List();

        // 基础列
        String[] theadArr = new String[]{"序号", "栋数", "单元", "楼层", "数量", "类型", "在刊客户", "待上刊客户"};
        int theadLength = theadArr.length, index = theadLength - 1;

        // 创建拍照要求
        setExcelByShootRequirement(sheet, font12CellStyle, leftCellStyle, index,
                String.join("", oneBuilding.getToInPublishShootRequirements()),
                String.join("", oneBuilding.getToUnPublishShootRequirements()));
        // 创建表头
        HSSFRow row3 = sheet.createRow(2);
        row3.setHeight((short) (25 * 20));
        HSSFCell cell3 = row3.createCell(0);
        cell3.setCellValue(building_name + "（" + oneBuilding.getPointCount() + "幅）");
        cell3.setCellStyle(titleCellStyle);
        // 设置跨行
        CellRangeAddress cellAddresses = new CellRangeAddress(2, 2, 0, index);
        sheet.addMergedRegion(cellAddresses);
        RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses, sheet);
        // 设置表头
        HSSFRow row4 = sheet.createRow(3);
        row4.setHeight((short) (30 * 20));
        setExcelThead(sheet, row4, theadCellStyle, theadArr);

        // 设置表格内容
        fillExcelTbody(sheet, tbodyCellStyle, 4, theadLength, list);
    }

    private static void setExcelByShootRequirement(HSSFSheet sheet, HSSFCellStyle cellStyle, HSSFCellStyle cellStyle2, int colLength,
                                                   String toInPublishStr, String toUnPublishStr) {
        HSSFRow row = sheet.createRow(0);
        row.setHeight((short) (40 * 20));
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("上刊客户");
        cell.setCellStyle(cellStyle);
        HSSFCell cell2 = row.createCell(1);
        if (StringUtils.isNotBlank(toInPublishStr) && toInPublishStr.length() >= 2) toInPublishStr = toInPublishStr.substring(0, toInPublishStr.length() - 2);
        cell2.setCellValue(toInPublishStr);
        cell2.setCellStyle(cellStyle2);
        // 设置跨行
        CellRangeAddress cellAddresses = new CellRangeAddress(0, 0, 1, colLength);
        sheet.addMergedRegion(cellAddresses);
        RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses, sheet);

        HSSFRow row2 = sheet.createRow(1);
        row2.setHeight((short) (40 * 20));
        HSSFCell cell2_1 = row2.createCell(0);
        cell2_1.setCellValue("下刊客户");
        cell2_1.setCellStyle(cellStyle);
        HSSFCell cell2_2 = row2.createCell(1);
        if (StringUtils.isNotBlank(toUnPublishStr) && toUnPublishStr.length() >= 2) toUnPublishStr = toUnPublishStr.substring(0, toUnPublishStr.length() - 2);
        cell2_2.setCellValue(toUnPublishStr);
        cell2_2.setCellStyle(cellStyle2);
        // 设置跨行
        CellRangeAddress cellAddresses2 = new CellRangeAddress(1, 1, 1, colLength);
        sheet.addMergedRegion(cellAddresses2);
        RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses2, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses2, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses2, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses2, sheet);
    }

    private static void setExcelThead(HSSFSheet sheet, HSSFRow row, HSSFCellStyle cellStyle, String[] arr) {
        int len = arr.length;
        for (int i = 0; i < len; i++) {
            int width = 8;
            if (i == 6 || i == 7) width = 19;
            sheet.setColumnWidth(i, width * 256);
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(arr[i]);
            cell.setCellStyle(cellStyle);
        }
        // 打印设置
        HSSFPrintSetup printSetup = sheet.getPrintSetup();
        printSetup.setLandscape(false);
        printSetup.setPaperSize(HSSFPrintSetup.A4_PAPERSIZE);//纸张
    }

    /**
     * 填充Excel
     *
     * @param list 数据
     * @rowIndex 当前行
     */
    public static void fillExcelTbody(HSSFSheet sheet, HSSFCellStyle cellStyle, int rowIndex, int colLength, List<WeekDetailVO2> list) {
        int idx = 1;
        int totalCount = 0;
        // 合并单元格
        Map<String, Integer> buildingMap = new HashMap<>(); // 第二个参数：需要合并行数
        Map<String, Integer> unitMap = new HashMap<>();
        for (WeekDetailVO2 vo2 : list) {
            String building_key = vo2.groupKeyByBuilding(),
                    unit_key = vo2.groupKeyByUnit();
            Integer building_number = buildingMap.get(building_key),
                    unit_number = unitMap.get(unit_key);

            if (building_number != null) {
                buildingMap.put(building_key, building_number + 1);
            } else {
                buildingMap.put(building_key, 0);
            }
            if (unit_number != null) {
                unitMap.put(unit_key, unit_number + 1);
            } else {
                unitMap.put(unit_key, 0);
            }
        }

        Set<String> buildingSet = new HashSet<String>();
        Set<String> unitSet = new HashSet<String>();

        for (WeekDetailVO2 vo2 : list) {
            HSSFRow row = sheet.createRow(rowIndex);
            row.setHeight((short) (24 * 20));
            for (int i = 0; i < colLength; i++) {
                HSSFCell cell = row.createCell(i);
                if (i == 0) cell.setCellValue(idx);
                else if (i == 1) cell.setCellValue(vo2.getBuilding_number() + "栋");
                else if (i == 2) cell.setCellValue(vo2.getUnit_number() + "单元");
                else if (i == 3) cell.setCellValue(vo2.getFloor() + "楼");
                else if (i == 4) {//数量
                    totalCount += vo2.getMedia_total_count();
                    cell.setCellValue(vo2.getMedia_total_count());
                } else if (i == 5) cell.setCellValue(vo2.getBuilding_second_type());//类型
                else if (i == 6) {//在刊客户
                    List<WeekDetailCustomerExt2> inPublish = vo2.getInPublish();
                    String str = "";
                    for (WeekDetailCustomerExt2 o : inPublish) {
                        str += o.getCustomerName() + "：" + o.getOccupyCount() + "个\r\n" + o.getBeginDateStr() + "-" + o.getEndDateStr() + " \r\n";
                    }
                    if (StringUtils.isNotEmpty(str) && str.length() > 4) str = str.substring(0, str.length() - 3);
                    cell.setCellValue(str);
                } else if (i == 7) {
                    List<WeekDetailCustomerExt2> waitPublish = vo2.getWaitPublish();
                    String str = "";
                    for (WeekDetailCustomerExt2 o : waitPublish) {
                        str += o.getCustomerName() + "：" + o.getOccupyCount() + "个\r\n" + o.getBeginDateStr() + "-" + o.getEndDateStr() + " \r\n";
                    }
                    if (StringUtils.isNotEmpty(str) && str.length() > 4) str = str.substring(0, str.length() - 3);
                    cell.setCellValue(str);
                }
                cell.setCellStyle(cellStyle);

                String building_key = vo2.groupKeyByBuilding(),
                        unit_key = vo2.groupKeyByUnit();

                Integer build_num = buildingMap.get(building_key),
                        unit_num = unitMap.get(unit_key);
                // 栋数设置跨行
                if (build_num != null && build_num > 0 && i == 1 && !buildingSet.contains(building_key)) {
                    buildingSet.add(building_key);
                    CellRangeAddress cellAddresses = new CellRangeAddress(rowIndex, rowIndex + build_num, i, i);
                    sheet.addMergedRegion(cellAddresses);
                    RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses, sheet);
                    RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses, sheet);
                    RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses, sheet);
                    RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses, sheet);
                }
                // 单元设置跨行
                if (unit_num != null && unit_num > 0 && i == 2 && !unitSet.contains(unit_key)) {
                    unitSet.add(unit_key);
                    CellRangeAddress cellAddresses = new CellRangeAddress(rowIndex, rowIndex + unit_num, i, i);
                    sheet.addMergedRegion(cellAddresses);
                    RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses, sheet);
                    RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses, sheet);
                    RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses, sheet);
                    RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses, sheet);
                }
            }
            idx++;
            rowIndex++;
        }
        HSSFRow row2 = sheet.createRow(rowIndex);
        row2.setHeight((short) (24 * 20));
        for (int i = 0; i < colLength; i++) {
            HSSFCell cell = row2.createCell(i);
            if (i == 4) cell.setCellValue(totalCount);
            else cell.setCellValue("");
            cell.setCellStyle(cellStyle);
        }
    }

    /**
     * 表格内容样式
     *
     * @param wb
     * @return
     */
    private static HSSFCellStyle setExcelTbodyCellStyle(HSSFWorkbook wb) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        // 设置边框
        cellStyle.setBorderBottom(BorderStyle.THIN); // 下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); // 左边框
        cellStyle.setBorderTop(BorderStyle.THIN); // 上边框
        cellStyle.setBorderRight(BorderStyle.THIN); // 右边框
        // 设置居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置字体
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 9); // 设置字体大小
        cellStyle.setFont(font); // 选择需要用到的字体格式
        // 设置自动换行:
        cellStyle.setWrapText(true); // 设置自动换行
        return cellStyle;
    }

    /**
     * 表头样式
     *
     * @param wb
     * @param style
     * @return
     */
    private static HSSFCellStyle setExcelTheadCellStyle(HSSFWorkbook wb, HSSFCellStyle style) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.cloneStyleFrom(style);
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setBold(true); // 字体加粗
        font.setFontHeightInPoints((short) 11); // 设置字体大小
        cellStyle.setFont(font); // 选择需要用到的字体格式
        return cellStyle;
    }

    /**
     * 标题样式
     *
     * @param wb
     * @param style
     * @return
     */
    private static HSSFCellStyle setExcelTitleCellStyle(HSSFWorkbook wb, HSSFCellStyle style) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.cloneStyleFrom(style);
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setBold(true); // 字体加粗
        font.setFontHeightInPoints((short) 16); // 设置字体大小
        cellStyle.setFont(font); // 选择需要用到的字体格式
        return cellStyle;
    }

    /**
     * 左对齐样式
     *
     * @param wb
     * @param style
     * @return
     */
    private static HSSFCellStyle setExcelLeftCellStyle(HSSFWorkbook wb, HSSFCellStyle style) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.cloneStyleFrom(style);
        cellStyle.setAlignment(HorizontalAlignment.LEFT);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 11); // 设置字体大小
        cellStyle.setFont(font); // 选择需要用到的字体格式
        return cellStyle;
    }

    /**
     * 字体12号
     *
     * @param wb
     * @param style
     * @return
     */
    private static HSSFCellStyle setExcelFont12CellStyle(HSSFWorkbook wb, HSSFCellStyle style) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.cloneStyleFrom(style);
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 12); // 设置字体大小
        cellStyle.setFont(font); // 选择需要用到的字体格式
        return cellStyle;
    }

}
